package com.shou.domain.common;

import com.shou.domain.user.model.entity.UserEntity;
import com.shou.types.annotation.Encrypted;
import com.shou.types.common.ReturnCodeEnum;
import com.shou.types.common.TableNameEnum;
import com.shou.types.exception.DataNotFoundException;
import com.shou.types.exception.DuplicateException;
import com.shou.types.exception.ExternalException;
import com.shou.types.exception.InvalidParameterException;
import com.shou.types.utils.RSAUtil;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.util.List;

/**
 * ClassName:AbstractService
 * Project:SmartPark
 * Package: com.shou.domain.common
 * Description
 *
 * @Author Nemo
 * @Create 2025/2/8 19:03
 * @Version 1.0
 */
public class AbstractService {
    @Resource
    IBaseRepository baseRepository;



    public void deleteByIds(List<Integer> ids, TableNameEnum tableNameEnum) {
        validExistByIds(ids, tableNameEnum);
        baseRepository.deleteByIds(ids, tableNameEnum.getEnTableName());
    }

    public void deleteAll(TableNameEnum tableNameEnum) {
        if(baseRepository.checkIfRecordsExist(tableNameEnum.getEnTableName())){
            baseRepository.deleteAllByTableName(tableNameEnum.getEnTableName());
        } else{
            throw new DataNotFoundException(DataNotFoundException.ErrorCodeEnum.NO_INFO_NEED_CLEAR, tableNameEnum.getCnTableName() + "内无信息，无需清空！", ReturnCodeEnum.RC406);
        }
    }
    /**
     * 根据ID列表检查是否存在于所在表
     * 用于批量操作，最大限制不超100条
     */
    protected void validExistByIds(List<Integer> ids, TableNameEnum tableNameEnum) {
        for (Integer id : ids) {
            if(!checkIfExistById(id, tableNameEnum))
                throw new DataNotFoundException(DataNotFoundException.ErrorCodeEnum.INFO_NOT_FOUND, "id: " + id, ReturnCodeEnum.RC410);
        }
    }

    /**
     * 根据ID检查是否存在于所在表
     */
    protected boolean checkIfExistById(Integer id, TableNameEnum tableNameEnum) {
        return baseRepository.checkIfExistById(id, tableNameEnum.getEnTableName());
    }

    protected void validateCode(String code, String tableName, Integer... excludeIds) {
       if(checkIfExistByCode(code, tableName, excludeIds)){
           throw new DuplicateException(DuplicateException.ErrorCodeEnum.DUPLICATE_INPUT_CODE, "编号: " + code, ReturnCodeEnum.RC406);
       }
    }

    protected boolean checkIfExistByCode(String code, String tableName, Integer... excludeIds) {
        return baseRepository.checkIfExistByCode(code, tableName, excludeIds);
    }

    /**
     * 同一停车场停车位编号不能重复
     */
    protected void validateByLotCode(String code, String tableName, String lotCode, Integer... excludeIds) {
        if(checkIfSpaceExistByCode(code, tableName, lotCode, excludeIds)){
            throw new DuplicateException(DuplicateException.ErrorCodeEnum.DUPLICATE_INPUT_CODE, "编号: " + code, ReturnCodeEnum.RC406);
        }
    }

    protected boolean checkIfSpaceExistByCode(String code, String tableName, String lotCode, Integer... excludeIds) {
        return baseRepository.checkIfSpaceExistByCode(code, tableName, excludeIds, lotCode);
    }

    /**
     * 用户名不可重复
     */
    protected void validateName(String name, String enTableName, Integer[] excludeIds) {
        if(checkIfExistByName(name, enTableName, excludeIds)){
            throw new DuplicateException(DuplicateException.ErrorCodeEnum.DUPLICATE_INPUT_USER_NAME, "请重新输入", ReturnCodeEnum.RC406);
        }
    }

    protected boolean checkIfExistByName(String name, String enTableName, Integer[] excludeIds) {
        return baseRepository.checkIfExistByName(name, enTableName, excludeIds);
    }

    /**
     * 用户预定车位的个数限制
     */
    protected void validateByReservedUserId(Integer userId, String enTableName, Integer[] excludeIds) {
        if(checkIfExistByReservedUserId(userId, enTableName, excludeIds)){
            throw new DuplicateException(DuplicateException.ErrorCodeEnum.DUPLICATE_RESERVED_INPUT_USER_ID, "请重新输入", ReturnCodeEnum.RC406);
        }
    }

    protected boolean checkIfExistByReservedUserId(Integer userId, String enTableName, Integer[] excludeIds) {
        return baseRepository.checkIfExistByReservedUserId(userId, enTableName, excludeIds);
    }

//    /**
//     * 用户入场记录的个数限制
//     */
//    protected void validateByUserId(Integer userId, String enTableName, Integer[] excludeIds) {
//        if(checkIfExistByReservedUserId(userId, enTableName, excludeIds)){
//            throw new DuplicateException(DuplicateException.ErrorCodeEnum.DUPLICATE_RESERVED_INPUT_USER_ID, "请重新输入", ReturnCodeEnum.RC406);
//        }
//    }
//
//    protected boolean checkIfExistByUserId(Integer userId, String enTableName, Integer[] excludeIds) {
//        return baseRepository.checkIfExistByReservedUserId(userId, enTableName, excludeIds);
//    }

    /**
     * 对车位是否可用的验证
     */
    protected void validateBySpaceCode(String spaceCode, String enTableName, Integer[] excludeIds) {
        if(spaceCode == null || spaceCode.isEmpty()){
            throw new InvalidParameterException(InvalidParameterException.ErrorCodeEnum.INVALID_SPACE_CODE, "spaceCode: " + spaceCode, ReturnCodeEnum.RC406);
        }
        if(!checkIfAvailableBySpaceCode(spaceCode, enTableName, excludeIds)){
            throw new DuplicateException(DuplicateException.ErrorCodeEnum.DUPLICATE_INPUT_SPACE_CODE, "spaceCode: " + spaceCode, ReturnCodeEnum.RC406);
        }
    }

    protected boolean checkIfAvailableBySpaceCode(String spaceCode, String enTableName, Integer[] excludeIds) {
        return baseRepository.checkIfAvailableBySpaceCode(spaceCode, enTableName, excludeIds);
    }

    /**
     * 检查查询参数合理性
     */
    protected void validateQueryParams(PageQueryEntity pageQueryEntity, TableNameEnum tableNameEnum) {
        // 检查排序参数
        validateSortParams(pageQueryEntity, tableNameEnum);
    }

    protected void validateSortParams(PageQueryEntity pageQueryEntity, TableNameEnum tableNameEnum) {
        String sortName = pageQueryEntity.getSortName();
        Integer sort = pageQueryEntity.getSort();

        if(!StringUtils.isBlank(sortName)){
            if(!getColumnsByEnTableName(tableNameEnum.getEnTableName()).contains(sortName)){
                throw new RuntimeException("排序字段不存在");
            }
            if(sort != null && !(sort == 1 || sort == 0)){
                throw new RuntimeException("排序参数错误,只能为0或1");
            }
        }
    }

    /**
     * 根据英文表名获取所有数据项名
     */
    private List<String> getColumnsByEnTableName(String enTableName) {
        return baseRepository.getColumnsByEnTableName(enTableName);
    }

    /**
     * 将驼峰命名法转换为下划线命名法
     * @param camelCase 驼峰命名法的字符串
     * @return 下划线命名法的字符串
     */
    public static String camelToSnake(String camelCase) {
        if (camelCase == null || camelCase.isEmpty()) {
            return camelCase;
        }
        StringBuilder snakeCase = new StringBuilder();
        for (char c : camelCase.toCharArray()) {
            if (Character.isUpperCase(c)) {
                if (snakeCase.length() > 0) {
                    snakeCase.append('_');
                }
                snakeCase.append(Character.toLowerCase(c));
            } else {
                snakeCase.append(c);
            }
        }
        return snakeCase.toString();
    }

    protected void handleDecryption(UserEntity entity) {
        try {
            for (Field field : entity.getClass().getDeclaredFields()) {
                if (field.isAnnotationPresent(Encrypted.class)) {
                    field.setAccessible(true);
                    Object value = field.get(entity);
                    if (value instanceof String && StringUtils.isNotBlank((String) value)) {
                        String decrypted = RSAUtil.decryptByPrivateKey((String) value);
                        field.set(entity, decrypted);
                    }
                }
            }
        } catch (Exception e) {
            throw new ExternalException(ExternalException.ErrorCodeEnum.DECRYPT_WITH_PRIVATE_KEY_FAILED, e.getMessage(), ReturnCodeEnum.RC422);
        }
    }
}
